Skip to main content

DevSecOps

Delivery practice for systems where a bad release can affect patient care. The techniques are the ordinary ones; the health-specific parts are the change control, the testing with realistic-but-not-real data, and the fact that many clinical platforms are long-lived and dependency-heavy.


Pipeline​

commit
│
├─ lint, unit tests
├─ dependency scan (known vulnerabilities in libraries)
├─ secret scan (credentials committed by accident)
├─ SAST (static analysis)
│
build
├─ container image build
├─ image scan (OS and library CVEs)
├─ SBOM generation
├─ image signing
│
test
├─ integration tests against synthetic data
├─ FHIR profile validation / conformance suite
├─ DAST against a running instance
│
deploy
├─ staging → automated verification
├─ change approval (for clinical systems)
└─ production → progressive rollout, monitored, reversible

The two steps most often missing in health deployments are conformance testing — validating that what the system emits still matches the implementation guide — and a tested rollback.


Test data​

Never production clinical data in a non-production environment. It is a disclosure, and it will end up on a laptop.

Options, in order of preference:

  1. Synthetic generation — Synthea produces realistic synthetic patient histories including FHIR bundles. The best default for functional testing.
  2. Purpose-built fixtures — hand-crafted cases covering the awkward scenarios: twins, name changes, estimated dates, merges, corrections.
  3. De-identified production data — only with a formal governance decision, documented re-identification risk assessment, and controls on the environment. See health data. Treat "de-identified" as a claim to be tested, not a property to be assumed.

Synthetic data has a limitation worth naming: it does not reproduce your population's naming conventions, data-entry error patterns or missingness. For tuning patient matching specifically, synthetic data is misleading, and a governed process using real data is necessary.


Infrastructure as code​

All infrastructure defined in version-controlled code, applied through a pipeline, never by hand in a console.

ToolRole
Terraform / OpenTofuProvisioning cloud and on-premises resources
AnsibleConfiguration management, especially for VM-based deployments
HelmPackaging Kubernetes applications
Argo CD / FluxGitOps — the cluster converges on the declared state in Git
KustomizeEnvironment overlays without templating

Why it matters here specifically: national health deployments have long lifetimes and high staff turnover. An environment that exists only as accumulated manual changes cannot be rebuilt after a disaster, and disaster recovery that depends on someone's memory is not disaster recovery.

GitOps adds a useful property for governance: the Git history is the change record. Who changed what, when, reviewed by whom — the audit trail a health regulator asks for, produced as a by-product.


Supply chain​

Health platforms tend to be large, old and dependency-rich. OpenMRS, DHIS2 and HAPI FHIR each pull in hundreds of transitive dependencies.

SBOM — a software bill of materials (CycloneDX or SPDX) listing every component and version. Generate one per build and store it with the artefact. Its value appears on the day a widely used library is found vulnerable and someone asks whether you are affected: with SBOMs, the answer takes minutes. Without them, it takes weeks.

Scanning:

ScanCatchesTools
DependencyKnown CVEs in librariesTrivy, Grype, Dependabot, OWASP Dependency-Check
Container imageOS package and library CVEsTrivy, Grype, Clair
SecretsCredentials in sourcegitleaks, trufflehog
IaCInsecure infrastructure configurationCheckov, tfsec, KICS
SASTCode-level flawsSemgrep, CodeQL
DASTRuntime vulnerabilitiesOWASP ZAP

Provenance. Sign images (Sigstore/cosign) and verify signatures at deployment, so that only artefacts your pipeline built can run.

Set a policy for what blocks a release. "No critical or high vulnerabilities in internet-facing components" is enforceable; "no vulnerabilities" is not, and a policy nobody can meet is ignored entirely.


Secrets​

No secrets in source control, container images, or environment files committed anywhere. Use a secrets manager (Vault, OpenBao, or the cloud provider's), inject at runtime, prefer short-lived dynamic credentials, and rotate on staff departure.

Scan for committed secrets in CI and across history — secrets committed and then removed remain in the Git history and remain compromised. Rotate anything found; deleting the commit is not remediation.


Change control for clinical systems​

Continuous deployment is appropriate for a reporting dashboard and inappropriate for a prescribing module. Tier your change process by clinical risk:

TierExampleProcess
LowDashboard, documentation, reporting queryAutomated deployment on merge
MediumData capture form, non-clinical workflowAutomated, with staged rollout and monitoring
HighClinical decision support, prescribing, terminology releaseClinical review, scheduled release, explicit approval, rehearsed rollback

Terminology and value set releases belong in the high tier, and are commonly treated as data rather than as change. A value set update can silently alter what a decision support rule fires on. Version them, test them, release them deliberately — see terminology services.

Rollback must be tested. Database migrations that cannot be reversed make rollback impossible; design migrations to be backward-compatible so that the previous application version can still run against the new schema.


Environments​

At minimum: development, a staging environment that materially resembles production, and production. For an exchange, add a partner sandbox — a persistent environment with synthetic data where point-of-service vendors develop and certify their integrations. Its absence is the most common cause of vendors testing against production.

Separate credentials, separate certificates and separate client registrations per environment. Reusing production credentials in staging is how staging becomes a path into production.


References​